import json
# 读取 hspList.json 文件
with open('hspList.json', 'r', encoding='utf-8') as f:
    hspList = json.load(f)

# genIsValid
def genIsValid(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):
    sql = sql0
    # 获取规则的 isValid，默认是 True
    isValid = ruleDatum.get('isValid', True)

    if isValid == False:
        # 如果 isValid 是 False，则实际上不查询。添加一个注释以及一个不可能的条件
        sql += "-- rule is not valid, no data will be returned\n"
        sql += "AND 1=0\n"
    
    return sql

# genPre
def genDate(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):
    sql = sql0
    # 获取规则的开始和结束日期，yyyy-mm-dd格式，字符串
    beginDate = ruleDatum.get('beginDate', '2099-12-31')
    endDate = ruleDatum.get('endDate', '1900-01-01')

    # 如果开始日期、结束日期的“日”部分是00，则校正至01
    if beginDate.endswith('-00'):
        beginDate = beginDate[:-2] + '01'
    if endDate.endswith('-00'):
        endDate = endDate[:-2] + '01'
    
    # 如果开始日期、结束日期的“月”部分是00，则校正至01
    if beginDate.endswith('-00'):
        beginDate = beginDate[:-3] + '01'
    if endDate.endswith('-00'):
        endDate = endDate[:-3] + '01'

    # 添加开始日期
    sql += f"AND d.item_time >= to_date('{beginDate}', 'yyyy-mm-dd')\n"

    # 添加结束日期
    sql += f"AND d.item_time <= to_date('{endDate}', 'yyyy-mm-dd')\n"

    return sql

def genHspLv(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):
    sql = sql0
    # 获取规则的 filter_pre，这些是筛选前的一些前提条件
    filter_pre = ruleAct['filter_pre']

    # 添加医院 hsp_abbr 的限制
    sql += f"AND d.hsp_abbr = '{hsp_abbr}'\n"

    # 添加医院级别限制。从hspList中获取当前hsp_abbr对应的医院级别
    hsp_lv = next((item['j_hsp_lv'] for item in hspList if item['hsp_abbr'] == hsp_abbr), None)
    if (hsp_lv=='1' or hsp_lv==1) and not filter_pre['is_lv1']:
        # 如果医院级别是1，且filter_pre中的is_lv1为False，则实际上不查询。添加一个注释以及一个不可能的条件
        sql += "-- not including lv1, no data will be returned\n"
        sql += "AND 1=0\n"
    elif (hsp_lv=='2' or hsp_lv==2) and not filter_pre['is_lv2']:
        sql += "-- not including lv2, no data will be returned\n"
        sql += "AND 1=0\n"
    elif (hsp_lv=='3' or hsp_lv==3) and not filter_pre['is_lv3']:
        sql += "-- not including lv3, no data will be returned\n"
        sql += "AND 1=0\n"
    
    return sql

def genInOrOut(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):
    filter_pre = ruleAct.get('filter_pre', {})
    sql = sql0

    # 添加 is_outpatient 与 is_inpatient 条件。优先判断 is_outpatient
    if not filter_pre.get('is_outpatient', True):
        sql += "AND d.j_isin = '1'\n"
    elif not filter_pre.get('is_inpatient', True):
        sql += "AND d.j_isin = '0'\n"
    
    return sql

def genSelfpaid(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):
    filter_pre = ruleAct.get('filter_pre', {})
    sql = sql0

    # 添加 is_selfpaid 条件
    if not filter_pre.get('is_selfpaid', True):
        # 这条明细的医保内金额要不等于0
        sql += "AND d.b <> 0\n"
    
    return sql

def genTrigger(ruleDatum, ruleAct, filterDatum, hsp_abbr, sql0):

    triggerObjApply = ruleAct.get('trigger_apply', [])
    triggerCodes = [trigger.get('j_code') for trigger in triggerObjApply if trigger.get('j_code')]
    triggerNames = ruleAct['trigger']
    # triggerNames 额外删减，将 triggerCodes 当中的 item_names, item_med_codes, item_hsp_codes, item_hsp_names当中有','的保留
    # 因为模糊查询性能很慢，所以只有 code 不能确定（即对应的names中有','的情况）才保留
    triggerNames = [
        name for name in triggerNames if next((True for datum in triggerObjApply if (
            ',' in (datum.get('names') or '') or
            ',' in (datum.get('med_codes') or '') or
            ',' in (datum.get('hsp_codes') or '') or
            ',' in (datum.get('hsp_names') or '')
        )), False)
    ]

    sql = sql0
    # 处理 triggerCodes 的 in 条件，考虑 in 1000 限制
    if triggerCodes:
        code_chunks = [triggerCodes[i:i+1000] for i in range(0, len(triggerCodes), 1000)]
        code_conds = []
        for chunk in code_chunks:
            codes_str = ",".join(f"'{code}'" for code in chunk)
            code_conds.append(f"d.item_j_code IN ({codes_str})")
        sql += "AND (\n    " + " OR\n    ".join(code_conds) + "\n)\n"
    else:
        # 如果没有triggerCodes，则相当于没有项目触发，添加一个不可能的条件
        sql += "-- no trigger codes, no data will be returned\n"
        sql += "AND 1=0\n"

    return sql
